<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Drum Machine</title>
    <style>
        @import url("https://fonts.googleapis.com/css?family=Russo+One");
        body {
            font-family: Russo One;
        }

        body {
            user-select: none;
            background-color: #8d8d8d;
        }

        #root {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }

        .inner-container {
            outline: 5px solid orange;
            position: relative;
            width: 660px;
            text-align: center;
            background-color: #b3b3b3;
        }
        .inner-container .pad-bank {
            width: 332px;
            height: 272px;
            display: inline-block;
            margin: 20px;
        }
        .inner-container .pad-bank .drum-pad {
            position: relative;
            float: left;
            width: 100px;
            height: 80px;
            margin-right: 10px;
            border-radius: 5px;
            padding-top: 35px;
            box-sizing: border-box;
            cursor: pointer;
        }
        .inner-container .logo {
            position: absolute;
            top: 5px;
            right: 10px;
        }
        .inner-container .logo .inner-logo {
            display: inline-block;
            font-style: italic;
            font-weight: bold;
            font-size: 20px;
        }
        .inner-container .controls-container {
            width: 240px;
            height: 272px;
            display: inline-block;
            margin: 40px 20px 0 10px;
            vertical-align: top;
        }
        .inner-container .controls-container .control {
            width: 100px;
            margin: auto;
        }
        .inner-container .controls-container .control p {
            margin-bottom: 0;
        }
        .inner-container .controls-container #display {
            width: 200px;
            background-color: gray;
            margin: 15px auto;
            padding: 15px;
            box-sizing: border-box;
        }

        .outer-select, .inner-container .controls-container .control .select {
            margin: auto;
            border: 1px solid black;
            width: 50px;
            height: 20px;
            padding: 1px;
            background-color: black;
        }

        .inner-select, .inner-container .controls-container .control .select .inner {
            width: 23px;
            height: 19px;
            background: blue;
            border: 1px solid black;
            box-sizing: border-box;
            cursor: pointer;
        }

        @media screen and (max-width: 650px) {
            .inner-container {
                transform: scale(0.7);
            }
        }
        [type=range] {
            -webkit-appearance: none;
            margin: 12.5px 0;
            width: 100%;
        }
        [type=range]:focus {
            outline: none;
        }
        [type=range]::-webkit-slider-runnable-track {
            width: 100%;
            height: 5px;
            cursor: pointer;
            transition: all .2s ease;
            box-shadow: 2px 2px 2px #222, 0 0 2px #2f2f2f;
            background: #424242;
            border: 1px solid #000;
            border-radius: 0;
        }
        [type=range]::-webkit-slider-thumb {
            box-shadow: 1px 1px 1px #111, 0 0 1px #1e1e1e;
            border: 0 solid #fff;
            height: 25px;
            width: 8px;
            border-radius: 0;
            background: blue;
            cursor: pointer;
            -webkit-appearance: none;
            margin-top: -11px;
        }
        [type=range]:focus::-webkit-slider-runnable-track {
            background: #4f4f4f;
        }
        [type=range]::-moz-range-track {
            width: 100%;
            height: 5px;
            cursor: pointer;
            transition: all .2s ease;
            box-shadow: 2px 2px 2px #222, 0 0 2px #2f2f2f;
            background: #424242;
            border: 1px solid #000;
            border-radius: 0;
        }
        [type=range]::-moz-range-thumb {
            box-shadow: 1px 1px 1px #111, 0 0 1px #1e1e1e;
            border: 0 solid #fff;
            height: 25px;
            width: 8px;
            border-radius: 0;
            background: blue;
            cursor: pointer;
        }
        [type=range]::-ms-track {
            width: 100%;
            height: 5px;
            cursor: pointer;
            transition: all .2s ease;
            background: transparent;
            border-color: transparent;
            border-width: 8px 0;
            color: transparent;
        }
        [type=range]::-ms-fill-lower {
            box-shadow: 2px 2px 2px #222, 0 0 2px #2f2f2f;
            background: #353535;
            border: 1px solid #000;
            border-radius: 0;
        }
        [type=range]::-ms-fill-upper {
            box-shadow: 2px 2px 2px #222, 0 0 2px #2f2f2f;
            background: #424242;
            border: 1px solid #000;
            border-radius: 0;
        }
        [type=range]::-ms-thumb {
            box-shadow: 1px 1px 1px #111, 0 0 1px #1e1e1e;
            border: 0 solid #fff;
            height: 25px;
            width: 8px;
            border-radius: 0;
            background: blue;
            cursor: pointer;
        }
        [type=range]:focus::-ms-fill-lower {
            background: #424242;
        }
        [type=range]:focus::-ms-fill-upper {
            background: #4f4f4f;
        }

    </style>
</head>
<body>
<div id='root'></div>
</body>
</html>
<script>
    // coded by @no-stack-dub-sack (github) / @no_stack_sub_sack (codepen)
    const projectName = 'drum-machine';
    localStorage.setItem('example_project', 'Drum Machine');

    const bankOne = [{
        keyCode: 81,
        keyTrigger: 'Q',
        id: 'Heater-1',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3'
    }, {
        keyCode: 87,
        keyTrigger: 'W',
        id: 'Heater-2',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-2.mp3'
    }, {
        keyCode: 69,
        keyTrigger: 'E',
        id: 'Heater-3',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-3.mp3'
    }, {
        keyCode: 65,
        keyTrigger: 'A',
        id: 'Heater-4',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-4_1.mp3'
    }, {
        keyCode: 83,
        keyTrigger: 'S',
        id: 'Clap',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3'
    }, {
        keyCode: 68,
        keyTrigger: 'D',
        id: 'Open-HH',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Dsc_Oh.mp3'
    }, {
        keyCode: 90,
        keyTrigger: 'Z',
        id: "Kick-n'-Hat",
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Kick_n_Hat.mp3'
    }, {
        keyCode: 88,
        keyTrigger: 'X',
        id: 'Kick',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3'
    }, {
        keyCode: 67,
        keyTrigger: 'C',
        id: 'Closed-HH',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Cev_H2.mp3'
    },
    ];

    const bankTwo = [{
        keyCode: 81,
        keyTrigger: 'Q',
        id: 'Chord-1',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_1.mp3'
    }, {
        keyCode: 87,
        keyTrigger: 'W',
        id: 'Chord-2',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_2.mp3'
    }, {
        keyCode: 69,
        keyTrigger: 'E',
        id: 'Chord-3',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_3.mp3'
    }, {
        keyCode: 65,
        keyTrigger: 'A',
        id: 'Shaker',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Give_us_a_light.mp3'
    }, {
        keyCode: 83,
        keyTrigger: 'S',
        id: 'Open-HH',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Dry_Ohh.mp3'
    }, {
        keyCode: 68,
        keyTrigger: 'D',
        id: 'Closed-HH',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Bld_H1.mp3'
    }, {
        keyCode: 90,
        keyTrigger: 'Z',
        id: 'Punchy-Kick',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/punchy_kick_1.mp3'
    }, {
        keyCode: 88,
        keyTrigger: 'X',
        id: 'Side-Stick',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/side_stick_1.mp3'
    }, {
        keyCode: 67,
        keyTrigger: 'C',
        id: 'Snare',
        url: 'https://s3.amazonaws.com/freecodecamp/drums/Brk_Snr.mp3'
    }];

    const activeStyle = {
        backgroundColor: 'orange',
        boxShadow: "0 3px orange",
        height: 77,
        marginTop: 13
    }

    const inactiveStyle = {
        backgroundColor: 'grey',
        marginTop: 10,
        boxShadow: "3px 3px 5px black"
    }

    class DrumPad extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                padStyle: inactiveStyle
            }
            this.playSound = this.playSound.bind(this);
            this.handleKeyPress = this.handleKeyPress.bind(this);
            this.activatePad = this.activatePad.bind(this);
        }
        componentDidMount() {
            document.addEventListener('keydown', this.handleKeyPress);
        }
        componentWillUnmount() {
            document.removeEventListener('keydown', this.handleKeyPress);
        }
        handleKeyPress(e) {
            if (e.keyCode === this.props.keyCode) {
                this.playSound();
            }
        }
        activatePad() {
            if (this.props.power) {
                this.state.padStyle.backgroundColor === 'orange' ?
                    this.setState({
                        padStyle: inactiveStyle
                    }) :
                    this.setState({
                        padStyle: activeStyle
                    });
            } else {
                this.state.padStyle.marginTop === 13 ?
                    this.setState({
                        padStyle: inactiveStyle
                    }) :
                    this.setState({
                        padStyle: {
                            height: 77,
                            marginTop: 13,
                            backgroundColor: 'grey',
                            boxShadow: "0 3px grey"
                        }
                    });
            }
        }
        playSound(e) {
            const sound = document.getElementById(this.props.keyTrigger);
            sound.currentTime = 0;
            sound.play();
            this.activatePad();
            setTimeout(() => this.activatePad(), 100);
            this.props.updateDisplay(this.props.clipId.replace(/-/g, ' '));
        }
        render() {
            return (
                <div id={this.props.clipId}
                     onClick={this.playSound}
                     className="drum-pad"
                     style={this.state.padStyle} >
                    <audio className='clip' id={this.props.keyTrigger} src={this.props.clip}></audio>
                    {this.props.keyTrigger}
                </div>
            )
        }
    }

    class PadBank extends React.Component {
        constructor(props) {
            super(props);
        }
        render() {
            let padBank;
            this.props.power ?
                padBank = this.props.currentPadBank.map((drumObj, i, padBankArr) => {
                    return (
                        <DrumPad
                            clipId={padBankArr[i].id}
                            clip={padBankArr[i].url}
                            keyTrigger={padBankArr[i].keyTrigger}
                            keyCode={padBankArr[i].keyCode}
                            updateDisplay={this.props.updateDisplay}
                            power={this.props.power} />
                    )
                }) :
                padBank = this.props.currentPadBank.map((drumObj, i, padBankArr) => {
                    return (
                        <DrumPad
                            clipId={padBankArr[i].id}
                            clip="#"
                            keyTrigger={padBankArr[i].keyTrigger}
                            keyCode={padBankArr[i].keyCode}
                            updateDisplay={this.props.updateDisplay}
                            power={this.props.power} />
                    )
                });
            return (
                <div className="pad-bank" >
                    {padBank}
                </div>
            )
        }
    }

    class App extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                power: true,
                display: String.fromCharCode(160),
                currentPadBank: bankOne,
                currentPadBankId: 'Heater Kit',
                sliderVal: 0.3
            }
            this.displayClipName = this.displayClipName.bind(this);
            this.selectBank = this.selectBank.bind(this);
            this.adjustVolume = this.adjustVolume.bind(this);
            this.powerControl = this.powerControl.bind(this);
            this.clearDisplay = this.clearDisplay.bind(this);
        }
        powerControl() {
            this.setState({
                power: !this.state.power,
                display: String.fromCharCode(160)
            });
        }
        selectBank() {
            if (this.state.power) {
                this.state.currentPadBankId === 'Heater Kit' ?
                    this.setState({
                        currentPadBank: bankTwo,
                        display: 'Smooth Piano Kit',
                        currentPadBankId: 'Smooth Piano Kit',
                    }) :
                    this.setState({
                        currentPadBank: bankOne,
                        display: 'Heater Kit',
                        currentPadBankId: 'Heater Kit',
                    });
            }
        }
        displayClipName(name) {
            if (this.state.power) {
                this.setState({
                    display: name
                });
            }
        }
        adjustVolume(e) {
            if (this.state.power) {
                this.setState({
                    sliderVal: e.target.value,
                    display: "Volume: " + Math.round(e.target.value * 100)
                });
                setTimeout(() => this.clearDisplay(), 1000);
            }
        }
        clearDisplay() {
            this.setState({
                display: String.fromCharCode(160)
            });
        }
        render() {
            const powerSlider = this.state.power ? {
                float: 'right'
            } : {
                float: 'left'
            };
            const bankSlider = this.state.currentPadBank === bankOne ? {
                float: 'left'
            } : {
                float: 'right'
            }; {
                const clips = [].slice.call(document.getElementsByClassName('clip'));
                clips.forEach(sound => {
                    sound.volume = this.state.sliderVal
                });
            }
            return (
                <div id="drum-machine" className="inner-container">
                    <PadBank
                        power={this.state.power}
                        updateDisplay={this.displayClipName}
                        clipVolume={this.state.sliderVal}
                        currentPadBank={this.state.currentPadBank} />

                    <div className="logo">
                        <div className="inner-logo ">{'FCC' + String.fromCharCode(160)}</div>
                        <i className="inner-logo fa fa-free-code-camp" />
                    </div>

                    <div className="controls-container">

                        <div className="control">
                            <p>Power</p>
                            <div onClick={this.powerControl} className="select">
                                <div style={powerSlider} className="inner" />
                            </div>
                        </div>
                        <p id="display">
                            {this.state.display}
                        </p>
                        <div className="volume-slider">
                            <input type="range" min="0" max="1" step="0.01" value={this.state.sliderVal} onChange={this.adjustVolume} />
                        </div>
                        <div className="control">
                            <p>Bank</p>
                            <div onClick={this.selectBank} className="select">
                                <div style={bankSlider} className="inner" />
                            </div>
                        </div>
                    </div>

                </div>
            )
        }
    }

    ReactDOM.render(
        <App />,
        document.getElementById('root')
    );
</script>